#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "modbustcp.h"
#include "modbus.h"

#define  MODBUS_TCP_DATA_SIZE                        20
#define  MODBUS_TCP_MAPPING_ADDR                     10001

#define  MODBUS_MAX_READ_BITS 2000

#define  MODBUS_MAX_READ_REGISTERS 125

void Modbus_Recive();
int ModbusTcp_Init();
void ModbusTcp_Uninit();


#define MODBUS_TCP_POLL_CONNECT_MAX         2               /* 最多支持的主机数量 */
#define MODBUS_TCP_DEFAULT_IP               "192.168.1.1"
#define MODBUS_TCP_FUNCTION                 7               /* modbus tcp的function所在位置的偏移字节数 */
pthread_mutex_t dataMutex = PTHREAD_MUTEX_INITIALIZER;
static modbus_t *mb = NULL;
static int socketMb = -1, clientMb = -1;

static modbus_mapping_t *Map = NULL;

int ModbusTcp_Init()
{
	// 创建从机TCP
	mb = modbus_new_tcp(MODBUS_TCP_DEFAULT_IP, 502);

	if(NULL == mb)
	{
		return -1;
	}

	//设置调试模式，打开会有收发报文打印
	// modbus_set_debug(mb, TRUE);

	// 侦听主站连接
	socketMb = modbus_tcp_listen(mb, MODBUS_TCP_POLL_CONNECT_MAX);

	//阻塞模式，等待主站连接请求，没有则继续等待
	// modbus_tcp_accept(mb, &socketMb);
	
	if(-1 == socketMb)
	{
		modbus_free(mb);
		mb = NULL;
		return -1;
	}
	else
	{
		// 设置为非阻塞
		int flags = fcntl(socketMb, F_GETFL, 0);
		fcntl(socketMb, F_SETFL, flags | O_NONBLOCK);
	}

	// 设置服务端等待客户端请求超时时间
	modbus_set_indication_timeout(mb, 3, 0);
	return 0;
}
static void ModbusTcp_Disconnect_Client()
{
	if(clientMb > 0)
	{
		close(clientMb);
		clientMb = -1;
	}
}
static void ModbusTcp_Disconnect_Server()
{
	if(socketMb > 0)
	{
		close(socketMb);
		socketMb = -1;
	}
}
void ModbusTcp_Uninit()
{
	modbus_mapping_free(Map);

	modbus_close(mb);
	modbus_free(mb);

	ModbusTcp_Disconnect_Server();
	ModbusTcp_Disconnect_Client();
}
void Modbus_Data()
{
	int i;
	int cnt = 0;
	//只读 查询
	Map = modbus_mapping_new_start_address(0, 0, 0, 0, 0, 0, MODBUS_TCP_MAPPING_ADDR, MODBUS_TCP_DATA_SIZE * 个数);
	//xxx 是U32格式 ，采用大端显示  
	Map->tab_input_registers[cnt++] = xxx >> 16;
	Map->tab_input_registers[cnt++] = xx;
	//
	Map->tab_input_registers[cnt++] = yyy;
	Map->tab_input_registers[cnt++] = 0;
	Map->tab_input_registers[cnt++] =
	.
	.
	.
	//有规律的地址  如从10001开始，一个包占20个地址，有很多个包。
	cnt += (MODBUS_TCP_DATA_SIZE * (i + 1) - cnt);

}
void Modbus_Recive()
{
	//MODBUS_TCP_MAX_ADU_LENGTH在标准库里面定义
	uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH] = {0};  
	// 接收请求
	if(mb != NULL)
	{
		int ret = modbus_receive(mb, query);
		if(ret != -1)
		{
			uint16_t address = (query[MODBUS_TCP_FUNCTION + 1] << 8) + query[MODBUS_TCP_FUNCTION + 2];  //获取modbus的查询起始地址
			//MODBUS_TCP_MAPPING_ADDR 设定判断条件
			if(address >= MODBUS_TCP_MAPPING_ADDR)
			{
				pthread_mutex_lock(&dataMutex);
				Modbus_Data();
				pthread_mutex_unlock(&dataMutex);
				modbus_reply(mb, query, ret, Map);
			}
			else
			{
				modbus_reply(mb, query, ret, Map);
			}
		}
		else
		{
			ModbusTcp_Disconnect_Client();
			clientMb = modbus_tcp_accept(mb, &socketMb);
		}
	}
}
